﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// 
    /// </summary>
    public enum MIXCHANNELS_MODE
    {
        NONE
    }

    /// <summary>
    /// Mixes the RGB channels of a given Bitmap
    /// Use for example a channel string to show which channels are mixed together
    /// </summary>
    public class MixChannels : BaseImageFilter
    {
        protected string[] m_aString = new string[3];

        protected MIXCHANNELS_MODE M_MODE = MIXCHANNELS_MODE.NONE;

        protected float fValueR = 0.0f;
        protected float fValueG = 0.0f;
        protected float fValueB = 0.0f;

        /// <summary>
        /// Default constructor
        /// </summary>
        public MixChannels()
            : this("GB", 50, "B", 50, "B", 5)
        {
        }

        /// <summary>
        /// Use this to mix r, g, b parts
        /// </summary>
        /// <param name="sRGB_R"></param>
        /// <param name="sRGB_G"></param>
        /// <param name="sRGB_B"></param>
        public MixChannels(string sRGB_R, string sRGB_G, string sRGB_B)
        {
            m_aString[0] = sRGB_R;
            m_aString[1] = sRGB_G;
            m_aString[2] = sRGB_B;
        }

        /// <summary>
        /// Use this to mix rchannels, gchannels, bchannels and specify percentage for each channel
        /// </summary>
        public MixChannels(string sRGB_R, int nPercent1, string sRGB_G, int nPercent2, string sRGB_B, int nPercent3)
            : this(sRGB_R, sRGB_G, sRGB_B)
        {
            fValueR = nPercent1;
            fValueG = nPercent2;
            fValueB = nPercent3;
        }

        /// <summary>
        /// Specify a factor for each channel string here
        /// </summary>
        /// <param name="sRGB_R"></param>
        /// <param name="fFactor1"></param>
        /// <param name="sRGB_G"></param>
        /// <param name="fFactor2"></param>
        /// <param name="sRGB_B"></param>
        /// <param name="fFactor3"></param>
        public MixChannels(string sRGB_R, float fFactor1, string sRGB_G, float fFactor2, string sRGB_B, float fFactor3)
            : this(sRGB_R, sRGB_G, sRGB_B)
        {
            fValueR = fFactor1;
            fValueG = fFactor2;
            fValueB = fFactor3;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_mixChannels"></param>
        internal MixChannels(MixChannels _mixChannels)
        {
            this.m_aString = _mixChannels.m_aString;
            this.fValueR = _mixChannels.fValueR;
            this.fValueG = _mixChannels.fValueG;
            this.fValueB = _mixChannels.fValueB;
            this.M_MODE = _mixChannels.M_MODE;
        }

        /// <summary>
        /// Get/set
        /// </summary>
        public MIXCHANNELS_MODE MODE
        {
            get { return M_MODE; }
            set { M_MODE = value; }
        }

        /// <summary>
        /// Gets or sets the R.
        /// </summary>
        /// <value>The R.</value>
        public float R
        {
            get { return fValueR; }
            set { fValueR = value; }
        }

        /// <summary>
        /// Gets or sets the G.
        /// </summary>
        /// <value>The G.</value>
        public float G
        {
            get { return fValueG; }
            set { fValueG = value; }
        }

        /// <summary>
        /// Gets or sets the B.
        /// </summary>
        /// <value>The B.</value>
        public float B
        {
            get { return fValueB; }
            set { fValueB = value; }
        }
        
        /// <summary>
        /// Executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;
            int[] aRGB = new int[3];

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            Color color = Color.Transparent;

            int y = 0;
            int x = 0;
            string sDef = string.Empty;
            int nChannelSum = 0;
            int nChannel = 0;
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = bitmap.GetPixel(x, y);

                    for (int i = 0; i < 3; i++)
                    {
                        sDef = m_aString[i];
                        nChannelSum = 0;
                        foreach (char chChar in sDef)
                        {
                            nChannel = ColorFunctions.GetColorChannel(color, ColorFunctions.GetRGBFromChar(chChar));
                            nChannelSum += nChannel;
                        }
                        aRGB[i] = nChannelSum / sDef.Length;
                    }

                    color = Color.FromArgb(aRGB[0], aRGB[1], aRGB[2]);
                    bitmap.SetPixel(x, y, color);
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// Use this to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new MixChannels(this);
        }
    }
}
